package com.mdhw.config;

import com.mdhw.admin.entity.AdminUser;
import com.mdhw.admin.service.AdminUserService;
import com.mdhw.admin.vo.AdminUserVo;
import com.mdhw.common.annotation.IgnorePermissions;
import com.mdhw.common.contants.CacheKeyContants;
import com.mdhw.common.enums.MessageEnum;
import com.mdhw.common.exception.BusException;
import com.mdhw.system.service.SysUserService;
import com.mdhw.utils.JwtUtil;
import com.mdhw.utils.RedisUtil;
import com.mdhw.utils.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 权限验证过滤器
 */
@Slf4j
@WebFilter(filterName = "AuthenticationFilter", urlPatterns = {"/*"})
public class AuthenticationFilter implements Filter {

    @Autowired
    private RedisUtil redisUtil;
    AntPathMatcher antPathMatcher = new AntPathMatcher();
    @Autowired
    @Qualifier("handlerExceptionResolver")
    private HandlerExceptionResolver resolver;
    @Autowired
    private AdminUserService adminUserService;

    //忽略请求地址
    public List<String> ignoreUrl
            = Arrays.asList(
            "/v2/api-docs",
            "/configuration/ui",
            "/swagger-resources/**",
            "/configuration/security",
            "/swagger-ui.html",
            "/swagger-ui/index.html",
            "/webjars/**",
            "/adminUser/login");

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //Filter.super.init(filterConfig);
        System.out.println("AuthenticationFilter---->init()");

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException ,BusException{
        HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
        String requestURI = httpRequest.getRequestURI();
        RequestMappingHandlerMapping requestMappingHandlerMapping = SpringUtil.getBeanByName("requestMappingHandlerMapping");
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
        for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()) {
            RequestMappingInfo key = entry.getKey();
            HandlerMethod method = entry.getValue();
            IgnorePermissions methodAnnotation = method.getMethodAnnotation(IgnorePermissions.class);
            if (methodAnnotation != null && key.getPatternsCondition().getPatterns().stream().anyMatch(pattern -> antPathMatcher.match(pattern, requestURI))) {
                //放行
                filterChain.doFilter(httpRequest, httpResponse);
                return;
            }
        }
        if (this.ignoreUrl.stream().anyMatch(pattern -> antPathMatcher.match(pattern, requestURI))) {
            //放行
            filterChain.doFilter(httpRequest, httpResponse);
            return;
        }
        // 获取请求对象头部token数据
        String token = null;
        try {
            token = JwtUtil.getRequestToken(httpRequest);
        } catch (Exception e){
            resolver.resolveException(httpRequest, httpResponse, null, new BusException(MessageEnum.TOKEN_ERROR));
            return;
        }
        //判断redis 是否存在token
        String userId = JwtUtil.parseToken(token);

        if(!this.redisUtil.hasKey(CacheKeyContants.ADMIN_USER_TOKEN+userId)){
            resolver.resolveException(httpRequest, httpResponse,
                    null, new BusException(MessageEnum.TOKEN_ERROR));
            return;
        }
        Boolean isAdmin = this.adminUserService.isAdmin(Long.parseLong(userId), null);
        if(isAdmin){
            filterChain.doFilter(servletRequest,servletResponse);
            return;
        }
        List<String> permissionList = (List<String>) redisUtil.get(CacheKeyContants.ADMIN_USER_PERMISSION + userId);
        if("/adminUser/selectAdminUserByToken".equals(requestURI)){
            permissionList.add("/adminUser/selectAdminUserByToken");
        }

        if(!permissionList.contains(requestURI)){
            resolver.resolveException(httpRequest, httpResponse,
                    null, new BusException(MessageEnum.NO_INTERFACE_PERMISSION));
            return;
        }

//        WebContextUtil.setUserToken(token);
        filterChain.doFilter(servletRequest,servletResponse);
    }


    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
